#include <Klein/Shader/FragmentDatabase.h>

bool FragmentDatabase::AddFragment(const FragmentRef& fragment)
{
	const FragmentIdentifier& fragmentIdentifier = fragment->GetIdentifier();
	const String& fragmentCategoryName = fragmentIdentifier.GetCategoryName();
	const String& fragmentClassName = fragmentIdentifier.GetClassName();
	const String& fragmentCategoryClassName = fragmentIdentifier.GetCategoryClassName();
	const String& fragmentName = fragmentIdentifier.GetName();
	const String& fragmentCompleteName = fragmentIdentifier.GetFragmentCompleteName();

	if (mNodes.find(fragmentCompleteName) != mNodes.end())
	{
		return false;
	}
	mNodes.insert(std::make_pair(fragmentCompleteName, fragment));

	std::map<String, std::set<String> >::iterator cccItr = mCategoryNamesToCategoryClassNames.find(fragmentCategoryName);
	if (cccItr == mCategoryNamesToCategoryClassNames.end())
	{
		std::set<String> fragmentNames;
		fragmentNames.insert(fragmentCategoryClassName);

		mCategoryNamesToCategoryClassNames.insert(std::make_pair(fragmentCategoryName, fragmentNames));
	}
	else
	{
		if (cccItr->second.find(fragmentCategoryName) == cccItr->second.end())
		{
			cccItr->second.insert(fragmentCategoryClassName);
		}
	}

	std::map<String, std::set<String> >::iterator ccnItr = mCategoryClassNamesToNodeNames.find(fragmentCategoryClassName);
	if (ccnItr == mCategoryClassNamesToNodeNames.end())
	{
		std::set<String> fragmentNames;
		fragmentNames.insert(fragmentName);

		mCategoryClassNamesToNodeNames.insert(std::make_pair(fragmentCategoryClassName, fragmentNames));
	}
	else
	{
		if (ccnItr->second.find(fragmentName) == ccnItr->second.end())
		{
			ccnItr->second.insert(fragmentName);
		}
	}

	mActivedFragmentCategoryName = fragmentCategoryName;

	return true;
}

FragmentRef FragmentDatabase::GetFragment(const FragmentIdentifier& fragmentIdentifier)
{
	std::map<String, FragmentRef>::const_iterator itr = mNodes.find(fragmentIdentifier.GetFragmentCompleteName());
	assert(itr != mNodes.end());

	return itr->second;
}

void FragmentDatabase::ActiveFragmentCategory(const String& activedFragmentCategoryName)
{
	mActivedFragmentCategoryName = activedFragmentCategoryName;
}

const String& FragmentDatabase::GetActivedFragmentCategoryName() const
{
	return mActivedFragmentCategoryName;
}

void FragmentDatabase::CollectFragmentCategoryNames(std::set<String>& categoryNames) const
{
	for (std::map<String, std::set<String> >::const_iterator itr = mCategoryNamesToCategoryClassNames.begin(); itr != mCategoryNamesToCategoryClassNames.end(); ++ itr)
	{
		categoryNames.insert(itr->first);
	}
}

void FragmentDatabase::CollectFragmentClassNames(const String& fragmentCategoryName, std::set<String>& fragmentClassNames) const
{
	std::map<String, std::set<String> >::const_iterator itr = mCategoryNamesToCategoryClassNames.find(fragmentCategoryName);
	if (itr != mCategoryNamesToCategoryClassNames.end())
	{
		for (std::set<String>::const_iterator cItr = itr->second.begin(); cItr != itr->second.end(); ++ cItr)
		{
			fragmentClassNames.insert(*cItr);
		}
	}
}

void FragmentDatabase::CollectFragments(const String& categoryClassName, std::vector<FragmentRef>& fragments) const
{
	for (std::map<String, FragmentRef>::const_iterator itr = mNodes.begin(); itr != mNodes.end(); ++ itr)
	{
		const FragmentIdentifier& fragmentIdentifier = itr->second->GetIdentifier();
		if (categoryClassName == fragmentIdentifier.GetCategoryClassName())
		{
			fragments.push_back(itr->second);
		}
	}
}
